package myJs.data.browse

import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.all._
import myJs.Implicits._
import myJs.api.Api
import myJs.cps.BootstrapTableCp.Column
import myJs.cps._
import myJs.myPkg.Hooks._
import myJs.myPkg.reactHookForm._
import myJs.tool.Pojo._
import myJs.tool.{Pojo, Tool}

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSON
import myJs.Implicits._

/** Created by yz on 21/1/2022
  */
object Cp {

  case class Props(keyword: String = "") {
    @inline def render: VdomElement = {
      Component(this)
    }
  }

  val Component = ScalaFnComponent[Props] { props =>
    val (columns, setColumns) = useState(List.empty[Column])
    val (initDatas, setInitDatas) = useState(List.empty[ujson.Obj])
    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (nutrients, setNutrients) = useState(List.empty[String])
    val (nutrientMap, setNutrientMap) = useState(SeqMap[String, String]())
    val useForm = ReactHookForm.useForm(UseFormOptions(mode = "onChange"))

    object FTool {

      def getColumns(infoMap: SeqMap[String, String], curDatas: List[ujson.Obj]): List[Column] = {
        val map = infoMap
        val basicColumns = map.map { case (k, v) =>
          val searchKind = k match {
            case "id" | "or" => NumericSearch
            case "nutrient" => OnlySort
            case _ => TextSearch
          }
          val fmt = FTool.tbFmt(k)
          val comVF = FTool.comVFmt(v)
          val optionMap = searchKind match {
            case Pojo.CheckboxSearch => curDatas.map(_(k).myStr).distinct.sorted.optionMap
            case _ => SeqMap[String, String]()
          }
          Column(
            field = k,
            title = v,
            operable = true,
            searchKind = searchKind,
            formatter = fmt,
            comVF = comVF,
            optionMap = optionMap
          )
        }.toList
        basicColumns
      }

      def tbFmt(field: String) = (v: ujson.Value, row: ujson.Obj) => {
        val aStyle = TagMod(
          cursor.pointer
        )
        field match {
          case "id" =>
            val detailUrl = g.jsRoutes.controllers.DataController.detailInfoBefore().url.toString
            a(
              aStyle,
              title := "Detail",
              href := s"${detailUrl}?id=${row("id").myStr}",
              target := "_blank",
              span(
                v.myStr
              )
            )()
          case "snpNumber" =>
            if (v.myStr.startsWith("rs") && v.myStr != "rs20607903") {
              val detailUrl = g.jsRoutes.controllers.DataController.detailInfoBefore().url.toString
              a(
                title := "Detail",
                href := s"${detailUrl}?id=${row("id").myStr}#anno",
                aStyle,
                target := "_blank",
                span(
                  v.myStr
                )
              )()
            } else {
              span(
                v.myStr
              )()
            }
          case "gene" =>
            a(
              href := s"https://www.genecards.org/cgi-bin/carddisp.pl?gene=${v.myStr}",
              aStyle,
              target := "_blank",
              v.myStr
            )()
          case _ => span(v.myStr)()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def refreshTableB = {
        Api.data.all.flatMap { response =>
          setInitDatas(response).async >>
            setDatas(response).async.map { x =>
              response
            }
        }
      }

      def formSubmit = useForm.myHandleSubmit((data: js.Dictionary[js.Any]) => {
        println(JSON.stringify(data))
        Callback {}.async
      })

    }

    useEffect(
      {
        FTool.refreshTableB.flatMapSync { curDatas =>
          val map = Tool.dataMap
          val curColumns = FTool.getColumns(map, curDatas)
          val nutrientMap = curDatas.map(_("nutrient").myStr).optionMap
          setColumns(curColumns) >>
            setNutrientMap(nutrientMap)
        }
      },
      List()
    )

    useEffect(
      {
        val curDatas = if (nutrients.isEmpty) {
          initDatas
        } else {
          initDatas.filter { x =>
            nutrients.contains(x("nutrient").myStr)
          }
        }
        setDatas(curDatas)
      },
      List(nutrients)
    )

    div(
      div(
        FormProvider(
          control = useForm.control,
          formState = useForm.formState,
          setValue = useForm.setValue _
        )(
          form(
            className := "form-horizontal",
            id := "form",
            onSubmit := FTool.formSubmit,
            RSelectMulInlineCp
              .Props(
                value = nutrients,
                label = "Related nutrients",
                name = s"nutrients",
                optionMap = nutrientMap,
                onChange = (v: List[String]) => setNutrients(v),
                inputWidth = 8
              )
              .render
          ),
          hr(),
          BootstrapTableCp
            .Props(
              columns = columns,
              datas = datas,
              pageList = List(10, 25, 50),
              pageSize = 10,
              search = true,
              allSearch = props.keyword
            )
            .render
        )
      )
    )

  }

}
